package bbs.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import bbs.entity.constants.Constants;
import bbs.entity.dto.FileUploadDto;
import bbs.entity.enums.*;
import bbs.entity.po.ForumArticle;
import bbs.entity.po.UserInfo;
import bbs.entity.po.UserMessage;
import bbs.entity.query.ForumArticleQuery;
import bbs.entity.query.UserInfoQuery;
import bbs.exception.BusinessException;
import bbs.mappers.ForumArticleMapper;
import bbs.mappers.UserInfoMapper;
import bbs.service.UserInfoService;
import bbs.service.UserMessageService;
import bbs.utils.FileUtil;
import bbs.utils.SysCacheUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import bbs.entity.query.ForumCommentQuery;
import bbs.entity.po.ForumComment;
import bbs.entity.vo.PaginationResultVO;
import bbs.entity.query.SimplePage;
import bbs.mappers.ForumCommentMapper;
import bbs.service.ForumCommentService;
import bbs.utils.StringTools;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;


/**
 * 评论 业务接口实现
 */
@Service("forumCommentService")
public class ForumCommentServiceImpl implements ForumCommentService {

	@Resource
	private ForumCommentMapper<ForumComment, ForumCommentQuery> forumCommentMapper;

	@Resource
	private ForumArticleMapper<ForumArticle, ForumArticleQuery> forumArticleMapper;

	@Resource
	private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;

	@Resource
	private UserInfoService userInfoService;

	@Resource
	private UserMessageService userMessageService;

	@Resource
	private FileUtil fileUtil;

	@Lazy
	@Resource
	private ForumCommentService forumCommentService;

	/**
	 * 根据条件查询列表
	 */
	@Override
	public List<ForumComment> findListByParam(ForumCommentQuery param)
	{
//		获取一级评论
		List<ForumComment> list = forumCommentMapper.selectList(param);
//		获取二级评论
		if(param.getLoadChildren() != null && param.getLoadChildren()){
			ForumCommentQuery subQuery = new ForumCommentQuery();
			subQuery.setQueryLikeType(param.getQueryLikeType());
			subQuery.setCurrentUserId(param.getCurrentUserId());
			subQuery.setArticleId(param.getArticleId());
			subQuery.setStatus(param.getStatus());
			subQuery.setLoadChildren(param.getLoadChildren());

			List<Integer> pcommentIdList = list.stream().map(ForumComment::getCommentId).distinct().collect(Collectors.toList());
			subQuery.setPcommentIdList(pcommentIdList);
			List<ForumComment> subCountryList = forumCommentMapper.selectList(subQuery);

			Map<Integer, List<ForumComment>> subMap = subCountryList.stream().collect(Collectors.groupingBy(ForumComment::getpCommentId));
			list.forEach(item -> {
				item.setChildren(subMap.get(item.getCommentId()));
			});
		}
		return list;
	}

	/**
	 * 根据条件查询列表
	 */
	@Override
	public Integer findCountByParam(ForumCommentQuery param) {
		return this.forumCommentMapper.selectCount(param);
	}

	/**
	 * 分页查询方法
	 */
	@Override
	public PaginationResultVO<ForumComment> findListByPage(ForumCommentQuery param) {
		int count = this.findCountByParam(param);
		int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

		SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
		param.setSimplePage(page);
		List<ForumComment> list = this.findListByParam(param);
		PaginationResultVO<ForumComment> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
		return result;
	}

	/**
	 * 新增
	 */
	@Override
	public Integer add(ForumComment bean) {
		return this.forumCommentMapper.insert(bean);
	}

	/**
	 * 批量新增
	 */
	@Override
	public Integer addBatch(List<ForumComment> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.forumCommentMapper.insertBatch(listBean);
	}

	/**
	 * 批量新增或者修改
	 */
	@Override
	public Integer addOrUpdateBatch(List<ForumComment> listBean) {
		if (listBean == null || listBean.isEmpty()) {
			return 0;
		}
		return this.forumCommentMapper.insertOrUpdateBatch(listBean);
	}

	/**
	 * 多条件更新
	 */
	@Override
	public Integer updateByParam(ForumComment bean, ForumCommentQuery param) {
		StringTools.checkParam(param);
		return this.forumCommentMapper.updateByParam(bean, param);
	}

	/**
	 * 多条件删除
	 */
	@Override
	public Integer deleteByParam(ForumCommentQuery param) {
		StringTools.checkParam(param);
		return this.forumCommentMapper.deleteByParam(param);
	}

	/**
	 * 根据CommentId获取对象
	 */
	@Override
	public ForumComment getForumCommentByCommentId(Integer commentId) {
		return this.forumCommentMapper.selectByCommentId(commentId);
	}

	/**
	 * 根据CommentId修改
	 */
	@Override
	public Integer updateForumCommentByCommentId(ForumComment bean, Integer commentId) {
		return this.forumCommentMapper.updateByCommentId(bean, commentId);
	}

	/**
	 * 根据CommentId删除
	 */
	@Override
	public Integer deleteForumCommentByCommentId(Integer commentId) {
		return this.forumCommentMapper.deleteByCommentId(commentId);
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public void changeTopType(String userId, Integer commentId, Integer topType) {
		CommentTopTypeEnum topTypeEnum = CommentTopTypeEnum.getByTYpe(topType);
		if (topTypeEnum == null) throw new BusinessException(ResponseCodeEnum.CODE_600);

		ForumComment forumComment = forumCommentMapper.selectByCommentId(commentId);
		if (forumComment == null) throw new BusinessException(ResponseCodeEnum.CODE_600);

		ForumArticle forumArticle = forumArticleMapper.selectByArticleId(forumComment.getArticleId());
		if (forumArticle == null) throw new BusinessException(ResponseCodeEnum.CODE_600);

		if (!forumArticle.getUserId().equals(userId) || forumComment.getpCommentId() != 0) throw new BusinessException(ResponseCodeEnum.CODE_600);
//		判断是否已置顶
		if (forumComment.getTopType().equals(topType)) return;

//		if (CommentTopTypeEnum.TOP.getType().equals(topType)) {
//		}
		forumCommentMapper.updateTopTypeByCommentId(forumComment.getCommentId(),topType);
	}

	/**
	 * 评论
	 * @param comment
	 * @param image
	 */
	@Override
	public void postComment(ForumComment comment, MultipartFile image) {
		ForumArticle forumArticle = forumArticleMapper.selectByArticleId(comment.getArticleId());
		if (forumArticle == null || !ArticleStatusEnum.AUDIT.getStatus().equals(forumArticle.getStatus())) {
			throw new BusinessException(Constants.ARTICLE_NOT_EXISTS);
		}
		ForumComment pComment = null;
		if (comment.getpCommentId() != 0) {
			pComment = forumCommentMapper.selectByCommentId(comment.getpCommentId());
			if (pComment == null) {
				throw new BusinessException(Constants.COMMENT_NOT_EXISTS);
			}
		}

//		判断回复的用户是否存在
		if (!StringUtils.isEmpty(comment.getReplyUserId())) {
			UserInfo userInfo = userInfoMapper.selectByUserId(comment.getReplyUserId());
			if (userInfo == null) {
				throw new BusinessException(Constants.USER_NOT_EXISTS);
			}
			comment.setReplyNickName(userInfo.getNickName());
		}

		if (image != null) {
			FileUploadDto uploadDto =  fileUtil.uploadFile2Local(image, Constants.FILE_FOLDER_IMAGE, FileUploadTypeEnum.COMMENT_IMAGE);
			comment.setImgPath(uploadDto.getLocalPath());
		}
		Boolean needAudit = SysCacheUtils.getSysSetting().getAuditSetting().getCommentAudit();

		comment.setStatus(needAudit ? ArticleStatusEnum.NO_AUDIT.getStatus() : ArticleStatusEnum.AUDIT.getStatus());
		forumCommentMapper.insert(comment);

		if (needAudit) return;

		updateCommentInfo(comment, forumArticle, pComment);
	}

	@Override
	public void delComment(String commentIds) {
		String[] commentIdArray = commentIds.split(",");
		for (String commentIdStr : commentIdArray) {
			Integer commentId = Integer.parseInt(commentIdStr);
			forumCommentService.delCommentSingle(commentId);
		}
	}

	@Override
	@Transactional
	public void delCommentSingle(Integer commentIds) {
		ForumComment comment = forumCommentMapper.selectByCommentId(commentIds);
		if (comment == null || ArticleStatusEnum.DEL.getStatus().equals(comment.getStatus())) return;

		ForumComment updateInfo = new ForumComment();
		updateInfo.setStatus(ArticleStatusEnum.DEL.getStatus());
		forumCommentMapper.updateByCommentId(updateInfo, commentIds);

		if (CommentStatusEnum.AUDIT.getStatus().equals(comment.getStatus())) {
			if (comment.getpCommentId() == 0) {
				forumArticleMapper.updateArticleCount(comment.getArticleId(), UpdateArticleCountTypeEnum.COMMENT_COUNT.getType(),-1 );
			}
			Integer integral = SysCacheUtils.getSysSetting().getCommentSetting().getCommentInteger();
			userInfoService.updateUserInternal(comment.getUserId(), UserIntegralOperTypeEnum.DEL_COMMENT, UserIntegralChangeTypeEnum.REDUCE.getChangeType(), integral);
		}
		UserMessage userMessage = new UserMessage();
		userMessage.setReceivedUserId(comment.getUserId());
		userMessage.setMessageType(MessageTypeEnum.SYS.getType());
		userMessage.setCreateTime(new Date());
		userMessage.setStatus(MessageStatusEnum.UNREAD.getStatus());
		userMessage.setMessageContent("评论“" + comment.getContent() + "”已被删除");
		userMessageService.add(userMessage);
	}

	@Override
	public void auditComment(String commentIds) {
		String[] commentIdArray = commentIds.split(",");
		for (String commentIdStr : commentIdArray) {
			Integer commentId = Integer.parseInt(commentIdStr);
			forumCommentService.auditCommentSingle(commentId);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void auditCommentSingle(Integer commentId) {
		ForumComment comment = forumCommentMapper.selectByCommentId(commentId);
		if (comment == null || !CommentStatusEnum.NO_AUDIT.getStatus().equals(comment.getStatus())) return;

		if (CommentStatusEnum.NO_AUDIT.getStatus().equals(comment.getStatus())) {
			comment.setStatus(CommentStatusEnum.AUDIT.getStatus());
			forumCommentMapper.updateByCommentId(comment, commentId);
			return;
		}

		ForumComment forumComment = new ForumComment();
		forumComment.setStatus(ArticleStatusEnum.AUDIT.getStatus());
		forumCommentMapper.updateByCommentId(forumComment, commentId);
		ForumArticle forumArticle = forumArticleMapper.selectByArticleId(comment.getArticleId());
		ForumComment pCommentInfo = null;
		if (comment.getpCommentId() != 0 && StringTools.isEmpty(comment.getReplyUserId())) {
			pCommentInfo = forumCommentMapper.selectByCommentId(comment.getpCommentId());
		}
		updateCommentInfo(comment, forumArticle, pCommentInfo);
	}

	@Override
	public void updateStatusBatchByUserId(Integer status, String userId) {

		forumCommentMapper.updateStatusBatchByUserId(status, userId);
	}


	public void updateCommentInfo(ForumComment comment, ForumArticle forumArticle, ForumComment pComment) {
		Integer commentIntegral = SysCacheUtils.getSysSetting().getCommentSetting().getCommentInteger();
		if ( commentIntegral > 0) {
			userInfoService.updateUserInternal(comment.getUserId(), UserIntegralOperTypeEnum.POST_COMMENT, UserIntegralChangeTypeEnum.ADD.getChangeType(), commentIntegral);
		}
		if (comment.getCommentId() == 0) {
			forumArticleMapper.updateArticleCount(comment.getArticleId(), Constants.ONE, UpdateArticleCountTypeEnum.COMMENT_COUNT.getType());
		}

		UserMessage userMessage = new UserMessage();
		userMessage.setArticleId(forumArticle.getArticleId());
		userMessage.setCreateTime(new Date());
		userMessage.setMessageType(MessageTypeEnum.COMMENT.getType());
		userMessage.setCommentId(comment.getCommentId());
		userMessage.setSendUserId(comment.getUserId());
		userMessage.setSendNickName(comment.getNickName());
		userMessage.setStatus(MessageStatusEnum.UNREAD.getStatus());
		userMessage.setArticleTitle(forumArticle.getTitle());
		if (comment.getpCommentId() == 0) {
			userMessage.setReceivedUserId(forumArticle.getUserId());
		} else if (comment.getpCommentId() != 0 && StringTools.isEmpty(comment.getReplyUserId())) {
			userMessage.setReceivedUserId(pComment.getUserId());
		} else if (comment.getpCommentId() != 0 && !StringTools.isEmpty(comment.getReplyUserId())) {
			userMessage.setReceivedUserId(comment.getReplyUserId());
		}
		if (!comment.getUserId().equals(userMessage.getReceivedUserId())) {
			userMessageService.add(userMessage);
		}
	}
}